package com.ansion.basedb.dao.impl;

import android.text.TextUtils;

import com.ansion.basedb.dao.DaoLoadHelper;
import com.ansion.basedb.dao.UserFTSHelper;
import com.ansion.basedb.dao.helper.UserHelper;
import com.ansion.basedb.dao.model.ContactsModel;
import com.ansion.basedb.dao.model.UserModel;
import com.ansion.basedb.notify.UserChangeNotifier;
import com.ansion.basedb.util.UserBroadcastUtils;
import com.ansion.log.VLog;
import com.ansion.string.StringUtils;
import com.ansion.utils.ContactUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class ContactsCacheDaoImpl extends ContactsDaoImpl {
    private final String TAG = "ContactsCacheDaoImpl";
	private Map<Long, ContactsModel> cacheMap = new ConcurrentHashMap<Long, ContactsModel>();
	private Set<Long> newJoinContact= new HashSet<Long>();
//	private AtomicBoolean isLoaded = new AtomicBoolean(false);
	private boolean isContactLoaded = false;
	@Override
	public void clearCache() {
		synchronized (this) {
			if (null != cacheMap) {
				cacheMap.clear();
			}
			isContactLoaded = false;
			DaoLoadHelper.contactsDaoLoadFinish = false;
		}
	}

	@Override
	public ContactsModel getContact(long uid) {
		ContactsModel contact = cacheMap.get(uid);
		if(!DaoLoadHelper.contactsDaoLoadFinish && contact == null)
		{
			contact = super.getContact(uid);
			if(contact != null)
				cacheContact(contact);
		}
		return contact;
	}



	@Override
	public List<ContactsModel> loadAll(boolean fromDb) {
		List<ContactsModel> contactList = null;
		if (DaoLoadHelper.contactsDaoLoadFinish) {
			contactList = new ArrayList<ContactsModel>();
			for (ContactsModel user : cacheMap.values()) {
				contactList.add(user);
			}
			VLog.e("loadAll", "loadAll size = "+contactList.size());
			return contactList;
		}
		synchronized (this) {
			if(fromDb){
				long t = System.currentTimeMillis();
				contactList = super.loadAll(fromDb);
				t  = System.currentTimeMillis() - t;
				VLog.e("time", "time load = "+t);
				if (contactList != null) {
					for (ContactsModel contact : contactList) {
						cacheContact(contact);
					}
				}
				DaoLoadHelper.contactsDaoLoadFinish = true;
				UserBroadcastUtils.sendContactChangeIntent(UserBroadcastUtils.kDAOCategory_LoadEnd);
			}
			return contactList;
		}
	}

	private void cacheContact(ContactsModel contact) {
		cacheMap.put(contact.getUserId(), contact);
	}

	@Override
	public void saveContact(ContactsModel contact) {
		synchronized (this) {
			ContactsModel oldContact = getContact(contact.getUserId());
			if (oldContact != null) {
				if (isContactChange(oldContact, contact)) {
					return;
				}
				cacheContact(contact);
			} else {
				cacheContact(contact);
			}
			super.saveContact(contact);
		}
	}

	private boolean isContactChange(ContactsModel oldContact,
			ContactsModel newContact) {
		if (oldContact.getContactId() == newContact.getContactId()
				&& StringUtils.stringIsEqual(oldContact.getFirstName(),
						newContact.getFirstName())
				&& StringUtils.stringIsEqual(oldContact.getMiddleName(),
						newContact.getMiddleName())
				&& StringUtils.stringIsEqual(oldContact.getLastName(),
						newContact.getLastName())
				&& oldContact.isHasAvatarInLocalAddress() == newContact
						.isHasAvatarInLocalAddress()) {
			return false;
		}
		return true;
	}

	@Override
	public void deleteContact(long uid) {
		synchronized (this) {
			cacheMap.remove(uid);
			super.deleteContact(uid);
		}
	}

	@Override
	public void deleteContacts(List<Long> uids) {
		synchronized (this) {
			for (long uid : uids) {
				cacheMap.remove(uid);
			}
			super.deleteContacts(uids);
		}
	}

	@Override
	public void checkAllContacts(List<ContactsModel> list,boolean isFirstLoad) {
		VLog.e("checkAllContacts", list.size()+"");
		synchronized (this) {
			if (null == list || list.isEmpty()) {
				deleteAll();
			} else {
				boolean hasChange = false;
				List<Long> deleteList = new ArrayList<Long>();
				Map<Long,ContactsModel> oldContactMap = new HashMap<>();
				List<ContactsModel> replaceList = new ArrayList<ContactsModel>();
				Iterator<ContactsModel>iterator = list.iterator();
				Set<Long> nowContactSet = new HashSet<Long>();
				Map<Long,ContactsModel> changedMap = new HashMap<>();
				while(iterator.hasNext()){
					ContactsModel contactsModel = iterator.next();
					ContactsModel oldContact = getContact(contactsModel
							.getUserId());
					oldContactMap.put(contactsModel.getUserId(),oldContact);
					if (oldContact != null) {
						if (isContactChange(oldContact, contactsModel)) {
							hasChange = true;
							contactsModel.generateSortKey();
							replaceList.add(contactsModel);
							cacheMap.put(contactsModel.getUserId(),
									contactsModel);
							changedMap.put(contactsModel.getUserId(),contactsModel);
						}
					} else {
						contactsModel.generateSortKey();
						hasChange = true;
						if(!isFirstLoad){
							newJoinContact.add(contactsModel.getUserId());
						}
						replaceList.add(contactsModel);
						cacheMap.put(contactsModel.getUserId(), contactsModel);
					}
					nowContactSet.add(contactsModel.getUserId());
				}
				Iterator<ContactsModel>mapIterator = cacheMap.values().iterator();
				while(mapIterator.hasNext()){
					ContactsModel contactsModel = mapIterator.next();
					if(!nowContactSet.contains(contactsModel.getUserId())){
						hasChange = true;
						deleteList.add(contactsModel.getUserId());
						oldContactMap.put(contactsModel.getUserId(),contactsModel);
						changedMap.put(contactsModel.getUserId(),contactsModel);
					}
				}
				Iterator<Long>deleteIterator = deleteList.iterator();
				while(deleteIterator.hasNext()){
					cacheMap.remove(deleteIterator.next());
				}
				if(hasChange){
					super.deleteContacts(deleteList);
                    for(Long userId:deleteList){

						//
						if(DaoLoadHelper.userDaoLoadFinish){
							UserModel userModel = UserHelper.getUserDBDao().getUserOnly(userId);
							ContactsModel oldContactsModel = oldContactMap.get(userId);
							boolean contactDisplayNameChanged = false;
							if(oldContactsModel != null && (!TextUtils.isEmpty(oldContactsModel.getFirstName()) || !TextUtils.isEmpty(oldContactsModel.getLastName()))){
								//老的firstName和lastName有一个不为空
								contactDisplayNameChanged = true;
							}
							//删除的时候，如果userModel是
                            if(userModel != null && TextUtils.isEmpty(userModel.getAvatarUrl())){
								if(contactDisplayNameChanged){
									VLog.d(TAG,"delete contact %d and avatar is null",userId);
									UserChangeNotifier.getInstance().notifyAvatarChange(String.valueOf(userId),userModel.getAvatarUrl());
								}
                            }
							if(contactDisplayNameChanged){
								VLog.d(TAG,"delete contact %d and displayName changed",userId);
								UserChangeNotifier.getInstance().notifyNameChange(String.valueOf(userId));
							}


						}


                    }
					super.saveContact(replaceList);
					for(ContactsModel contactsModel:replaceList){
                        long userId = contactsModel.getUserId();
						ContactsModel oldContact = oldContactMap.get(userId);
						ContactsModel newContact = cacheMap.get(userId);
						String oldDisplayName = oldContact == null ? ContactUtil.getFormatPhone(userId) : oldContact.getDisplayName(true);
						String newDisplayName = newContact == null ? ContactUtil.getFormatPhone(userId) : newContact.getDisplayName(true);
						if(!StringUtils.stringIsEqual(oldDisplayName,newDisplayName)){
							VLog.d(TAG,"contact changed %d and displayName changed",userId);
							UserChangeNotifier.getInstance().notifyNameChange(String.valueOf(userId));
						}
                        if(DaoLoadHelper.userDaoLoadFinish){
                            UserModel userModel = UserHelper.getUserDBDao().getUserOnly(userId);
                            if(userModel != null && TextUtils.isEmpty(userModel.getAvatarUrl())){

								String oldAvatarDisplayText = ContactUtil.getDisplayText(String.valueOf(userId) , oldContact == null ? null : oldContact.getFirstName(),oldContact == null ? null : oldContact.getLastName());
								String newAvatarDisplayText = ContactUtil.getDisplayText(String.valueOf(userId) , newContact == null ? null : newContact.getFirstName(),newContact == null ? null : newContact.getLastName());
                                if(!StringUtils.stringIsEqual(oldAvatarDisplayText,newAvatarDisplayText)){
									VLog.d(TAG,"contact changed %d and avatar is null",userId);
									UserChangeNotifier.getInstance().notifyAvatarChange(String.valueOf(userId),userModel.getAvatarUrl());
								}
                            }


						}
					}

				}
				VLog.e("contact change-------------", "haschange="+hasChange);

				//处理名字变更的和删除的
				UserFTSHelper.indexUser(changedMap);


			}
			if(!isContactLoaded){
				isContactLoaded = true;
                UserBroadcastUtils.sendContactChangeIntent(UserBroadcastUtils.kDAOCategory_LoadEnd);
			}
		}

	}

	@Override
	public void deleteAll() {
		synchronized (this) {
			if (null != cacheMap) {
				cacheMap.clear();
			}
			super.deleteAll();
		}
	}

	@Override
	public boolean isContactLoaded() {
		return isContactLoaded;
	}

	@Override
	public void setContactLoaded() {
		if(!isContactLoaded){
			isContactLoaded = true;
            UserBroadcastUtils.sendContactChangeIntent(UserBroadcastUtils.kDAOCategory_LoadEnd);
		}
	}


}
